﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using MySql.Data.MySqlClient;
using CPAIS.LogParser;
using CPAIS.DbAccessor;
using CPAIS.Model;
using CPAIS.Web.DbAccessors;
using System.Data.Common;
using System.Web.SessionState;
using CPAIS.Updater;
using System.IO;

namespace CPAIS.Web
{
    public class DSManager
    {
        private LogParserFactory lpFactory;
        private DbAccessorFactory daFactory;

        /// <summary>
        /// Default constructor.
        /// </summary>
        public DSManager()
        {
            lpFactory = new LogParserFactory(ParseMode.UsingXmlReader, false);
            daFactory = new DbAccessorFactory();

            lpFactory.AddLogParser(typeof(CPAIS.LogParser.PluginsWithXmlReader.LogParserA));
            lpFactory.AddLogParser(typeof(CPAIS.LogParser.PluginsWithXmlReader.LogParserB));
            lpFactory.AddLogParser(typeof(CPAIS.LogParser.PluginsWithXmlReader.LogParserC));
            lpFactory.AddLogParser(typeof(CPAIS.LogParser.PluginsWithXmlReader.LogParserD));

            daFactory.DbAccessor = new MySQLAccessor();
            // daFactory.DbAccessor = new SQLServerAccessor();
        }

        /// <summary>
        /// Gets the connection state to database.
        /// </summary>
        private bool IsDbEstablished
        {
            get
            {
                bool state = false;

                try
                {
                    using (DbConnection conn = daFactory.DbAccessor.CreateConnection())
                    {
                        conn.Open();
                        state = conn.State == System.Data.ConnectionState.Open;
                    }
                }
                catch (Exception)
                { }

                return state;
            }
        }

        /// <summary>
        /// Gets log parser factory.
        /// </summary>
        public LogParserFactory LPFactory { get { return lpFactory; } }

        /// <summary>
        /// Gets the root directory of event logs.
        /// </summary>
        public string RootOfOriginalEventLogs
        {
            get
            {
                return Constants.RootOfOriginalLogs.Replace('/', '\\').Replace("~\\", AppDomain.CurrentDomain.BaseDirectory);
            }
        }

        /// <summary>
        /// Gets the root directory of serialized event logs.
        /// </summary>
        private string RootOfSerializedEventLogs
        {
            get
            {
                return Constants.RootOfSerializedLogs.Replace('/', '\\').Replace("~\\", AppDomain.CurrentDomain.BaseDirectory);
            }
        }

        /// <summary>
        /// Gets event name log models.
        /// <param name="mode">if return is true, it is DB mode, else if File mode</param>
        /// </summary>
        public List<string> ListsEventLogs(out bool mode)
        {
            List<string> eventLogNames = new List<string>();
            if (IsDbEstablished)
            {
                mode = true;
                using (DbConnection conn = daFactory.DbAccessor.CreateConnection())
                {
                    DbDataReader reader = null;
                    conn.Open();
                    DbCommand cmd = daFactory.DbAccessor.CreateCommand();
                    cmd.Connection = conn;
                    cmd.CommandText = string.Format("SELECT Name FROM log WHERE Valid={0} ORDER BY Name ASC", 1);
                    reader = cmd.ExecuteReader();
                    while (reader.Read())
                    {
                        eventLogNames.Add(reader.GetString(0));
                    }
                }
            }
            else
            {
                mode = false;
                string rootDirName = RootOfSerializedEventLogs;
                DirectoryInfo rootDir = new DirectoryInfo(rootDirName);
                if (!rootDir.Exists)
                    rootDir.Create();
                var files = rootDir.GetFiles();
                foreach (var file in files)
                {
                    eventLogNames.Add(file.Name);
                }
            }
            return eventLogNames;
        }

        /// <summary>
        /// Loads log model, from database or from serialized event log file.
        /// </summary>
        public LogModel LoadLogModel(string logName, StateUpdater updater)
        {
            if (IsDbEstablished)
            {
                return daFactory.LoadLog(logName, updater);
            }
            else
            {
                string pathName = Path.Combine(RootOfSerializedEventLogs, logName);
                LogModel logModel = new LogModel();
                logModel.Deserialze(pathName, updater);
                return logModel.Valid ? logModel : null;
            }
        }

        /// <summary>
        /// Saves the log model to database to XML file.
        /// </summary>
        public void SaveLogModel(LogModel logModel, ProgressUpdater updater = null)
        {
            if (IsDbEstablished)
                daFactory.SaveLog(logModel, updater);
            else
            { 
                string pathName = Path.Combine(RootOfSerializedEventLogs, logModel.LogName);
                if (!File.Exists(pathName))
                    logModel.Serialize(pathName, updater);
            }
        }
    }
}